<template>
  <div class="oms-upload">
    <el-upload
      ref="omsUploadRef"
      :class="{
        'upload-hidden-icon': fileList.length === limit,
        'no-transition': noTransition
      }"
      v-model:file-list="fileList"
      action=""
      list-type="picture-card"
      :accept="accept"
      :before-upload="beforeUpload"
      :limit="limit"
      :multiple="multiple"
      :http-request="requestUpload"
      :on-preview="previewImg"
      :on-exceed="onExceed"
    >
      <el-icon><Plus /></el-icon>
      <template #file="{ file }">
        <div
          v-loading="
            file.status === 'uploading'
              ? {
                  text: `${file.percentage}%`,
                  spinner: loadingSvg,
                  svgViewBox: `-10, -10, 50, 50`
                }
              : false
          "
          style="width: 100%; height: 100%"
        >
          <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
          <span class="el-upload-list__item-actions">
            <span @click="previewImg(file)">
              <el-icon><zoom-in /></el-icon>
            </span>
            <span @click="editImg(file)">
              <el-icon><Edit /></el-icon>
            </span>
            <span @click="removeImg(file)">
              <el-icon><Delete /></el-icon>
            </span>
          </span>
        </div>
      </template>
    </el-upload>
    <zx-image-viewer
      v-model:show="isShowPreview"
      :initialIndex="initialIndex"
      :previewSrcList="previewSrcList"
    />
  </div>
</template>

<script setup>
import { upload } from '@/api/login';
import { IMG_URL } from '@/utils/const';
const props = defineProps({
  limit: {
    type: Number,
    default: 1
  },
  multiple: {
    type: Boolean,
    default: false
  },
  imgList: {
    type: Array,
    default: () => []
  },
  noTransition: {
    type: Boolean,
    default: false
  },
  // 最大像素宽
  maxWidth: {
    type: [Number, String],
    default: undefined
  },
  // 最大像素高
  maxHeight: {
    type: [Number, String],
    default: undefined
  },
  // 最大多少M
  maxSize: {
    type: [Number, String],
    default: 2
  }
});
const emit = defineEmits();

const loadingSvg = `
        <path class="path" d="
          M 30 15
          L 28 17
          M 25.61 25.61
          A 15 15, 0, 0, 1, 15 30
          A 15 15, 0, 1, 1, 27.99 7.5
          L 15 15
        " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
      `;

// 图片列表，有默认值则直接赋值默认值
const fileList = ref([]);
watch(
  () => props.imgList,
  val => {
    fileList.value = val || [];
  },
  { immediate: true }
);
// 上传前
function beforeUpload(file) {
  return new Promise((resolve, reject) => {
    validFile(file)
      .then(res => {
        resolve(res);
      })
      .catch(() => {
        reject();
      });
  });
}

// 校验文件格式
const accept = ref('image/jpeg,image/png');
function validFile(file) {
  return new Promise((resolve, reject) => {
    const typeList = ['image/jpeg', 'image/png'];
    const fileType = file.type;
    if (!typeList.includes(fileType)) {
      $msg.error('不支持该文件类型');
      reject();
      return;
    }

    const fileSize = file.size;
    if (fileSize / 1024 / 1024 > props.maxSize) {
      $msg.error(`超过${props.maxSize}M大小限制`);
      reject();
      return;
    }
    resolve(file);
  });
}

// 超数量限制
function onExceed(files, uploadFiles) {
  $msg.warning(
    `当前限制 ${props.limit} 张图片, 本次选择了 ${files.length} 张图片, 共选择了
      ${files.length + uploadFiles.length} 张`
  );
}

// 上传
function requestUpload(fileInfo) {
  const file = fileInfo.file || {};
  fileList.value.forEach(item => {
    if (item.uid === file.uid) {
      httpUpload(file, item);
    }
  });
}
async function httpUpload(file, item) {
  const formData = new FormData();
  formData.append('file', file);
  item.status = 'uploading';
  item.percentage = 0;
  emit('changeImgs', fileList.value);
  try {
    const res = await upload(formData, progressEvent => {
      const loaded = progressEvent.loaded;
      const total = progressEvent.total;
      item.percentage = Math.round((loaded / total) * 100);
      if (item.percentage > 100) item.percentage = 100;
    });
    item.resUrl = res.data?.uri || '';
    item.url = IMG_URL(item.resUrl);
    item.status = 'success';
    emit('changeImgs', fileList.value);
  } catch {
    fileList.value.forEach((item, index) => {
      if (item.uid === file.uid) {
        fileList.value.splice(index, 1);
      }
    });
    emit('changeImgs', fileList.value);
  }
}
// 预览图片
const isShowPreview = ref(false);
const initialIndex = ref(0);
const previewSrcList = ref([]);
function previewImg(file) {
  fileList.value.forEach((item, index) => {
    if (item.uid === file.uid) {
      initialIndex.value = index;
    }
  });
  previewSrcList.value = fileList.value.map(item => item.url);
  isShowPreview.value = true;
}

// 删除图片
function removeImg(file) {
  fileList.value.forEach((item, index) => {
    if (item.uid === file.uid) {
      fileList.value.splice(index, 1);
    }
  });
  emit('changeImgs', fileList.value);
}

// 替换图片
const omsUploadRef = ref();
function editImg(oldFile) {
  const fileInput = document.createElement('input');
  fileInput.type = 'file';
  fileInput.accept = accept.value;
  fileInput.onchange = () => {
    const newFile = fileInput.files?.[0];
    if (!newFile) return;
    validFile(newFile).then(() => {
      const index = fileList.value.findIndex(item => item.uid === oldFile.uid);
      fileList.value.splice(index, 1);
      omsUploadRef.value.handleStart(newFile);
      omsUploadRef.value.submit();
    });
  };
  fileInput.click();
}
</script>

<style lang="scss" scoped>
.upload-hidden-icon {
  :deep(.el-upload) {
    display: none;
  }
}
.oms-upload {
  :deep(.el-icon--close-tip) {
    display: none !important;
  }
  :deep(.el-upload-list__item-status-label) {
    display: none !important;
  }
  :deep(.el-progress-circle) {
    display: none;
  }
  :deep(.el-progress__text) {
    &::after {
      content: '上传中...';
    }
    span {
      display: none;
    }
  }
  :deep(.el-upload--picture-card) {
    --el-upload-picture-card-size: 100px;
  }
  :deep(.el-upload-list--picture-card) {
    --el-upload-list-picture-card-size: 100px;
  }
}
.no-transition {
  :deep(.el-upload-list__item) {
    transition: all 0s;
  }
}
:deep(.el-loading-spinner) {
  top: 0 !important;
  margin-top: 0 !important;
  height: 100%;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  svg {
    width: 42px !important;
    height: 42px !important;
    margin-top: 5px;
  }
  .el-loading-text {
    width: 100%;
    margin-top: -7px;
  }
}
:deep(.el-loading-mask) {
  z-index: 9;
}
.el-upload-list__item-actions {
  z-index: 10;
}
</style>
